#include "bot.h"
#include "stock.h"
#include "chrono.h"

#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::posix_time;
using namespace boost::gregorian;

#include <iostream>
using namespace std;

extern chrono clk;

bot::bot (const std::string& _name, const std::string& _symbol, int hs, int ms, int ss, int he, int me, int se, int _exec, int _num_shares, double _finish_price, double _stop_price) : cmp (_exec) {
  
  state = off;
  
  name = _name;
  
  symbol = _symbol;
  
  startt = ptime (day_clock::local_day (), hours (hs) + minutes (ms) + seconds (ss));
  endt = ptime (day_clock::local_day (), hours (he) + minutes (me) + seconds (se));
  availd = time_duration (endt - startt);
  
  time_duration startd (startt - clk.market_open);
  time_duration endd (endt - clk.market_open);
  
  start_time = startd.total_seconds ();
  end_time = endd.total_seconds ();
  avail_time = end_time - start_time;
  avail_time_1 = 1.0 / avail_time;
  
  last_trade.secs = start_time;
    
  exec = _exec;
  num_shares = _num_shares;
  
  stop_price = _stop_price;
  finish_price = _finish_price;
    
  num_trades = 0;
  position = 0;
  value = 0;
  
  
}

void bot::execute (double _price, int _size, double secs) {

  last_trade.price = _price;
  last_trade.size = _size;
  last_trade.secs = secs;

  position += _size;
  value += (_size * _price);

  last_trade.nor_pos = position * 100. / num_shares;  
  last_trade.nor_time = (secs - start_time) * avail_time_1;

  trades.push_back (last_trade);

  cout << "position: " << position << " nor_pos = " << last_trade.nor_pos << " nor_time: " << last_trade.nor_time << endl;
  
  ++num_trades;  
  
}

int bot::run (double secs) {
  
  int isecs = (int) secs;
  if (isecs >= start_time && isecs <= end_time) {
    double elapsed_time = secs - last_trade.secs;
    double trade_interval = get_trade_interval ();
    double trade_time = last_trade.secs;
    while (elapsed_time >= trade_interval) {
      elapsed_time -= trade_interval;
      stock* ps = get_stock_ptr (symbol);
      if (ps) {
        double price = ps->price.value;
        trade_time += trade_interval;
        if (cmp (price, stop_price)) { // execute as price is better than stop price
          int remaining_size = num_shares - position;
          if (remaining_size <= 0) { // job done
            if (state != finished) cout << name << ' ' << num_shares << ' ' << position << " finished" << endl;
            state = finished;
          } else {
            if (cmp (price, finish_price)) { // finish order at this price              
              execute (price, remaining_size, trade_time);
              state = finished;
              cout << "finished " << remaining_size << " at " << price << " with finish price: " << finish_price << endl;
            } else { // trade              
              int size = min (get_trade_size (trade_time), remaining_size);
              execute (price, size, trade_time);
              state = on;
              cout << name << ' ' << symbol << "size = " << size << " position = " << position << ", remaining = " << (num_shares - position) << " value = " << value << endl;
            }
          }
        } else {
          if (state != off) cout << name << ' ' << symbol << " stop price: " << stop_price << " reached!" << endl;
          state = off;
        }
      }
    }
    return 1;
  } else {
    if (state != off) cout << "bot is off" << endl;
    state = off;
    return 0;
  }
}

int comparer::operator () (double price1, double price2) {
  if (exec == bot::buy) {
    return price1 <= price2;
  } else if (exec == bot::sell) {
    return price1 >= price2;
  } else return 0;
}
